/*
 * Copyright (c) 2022 HiSilicon (Shanghai) Technologies CO., LIMITED.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <hi_task.h>
#include <string.h>
#include <hi_wifi_api.h>
#include <hi_mux.h>
#include <hi_io.h>
#include <hi_gpio.h>
#include "iot_config.h"
#include "iot_log.h"
#include "iot_main.h"
#include "iot_profile.h"
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "iot_gpio.h"
#include "app_mqtt_iot.h"
#include <math.h>
/*motor*/
#include "robot_motor.h"
#include "robot_encoder.h"

/*beep*/
#include "beep.h"

/* attribute initiative to report */
#define TAKE_THE_INITIATIVE_TO_REPORT
#define ONE_SECOND                          (1000)
/* oc request id */
#define CN_COMMADN_INDEX                    "commands/request_id="
#define WECHAT_SUBSCRIBE_LIGHT              "light"
#define POWERSWITCH_ON "1"
#define POWERSWITCH_OFF "0"
#define WECHAT_SUBSCRIBE_LIGHT_ON_STATE     "1"
#define WECHAT_SUBSCRIBE_LIGHT_OFF_STATE    "0"

#define GPIO2 2
#define GPIO11 11
#define GPIO12 12
#define TASK_STAK_SIZE    (1024*10)
#define TRACKING_MODE 1
#define INDENTIFY_MODE 0
#define IOT_PWM_PORT_PWM2 2
#define MODE_NONE 0
#define MODE_TRACKING 170         // 跟随模式
#define MODE_IDENTIFY 255         // 识别模式

/* 全局变量 */
int Detect_Mode = MODE_NONE;
hi_bool On_Mode_Change = HI_FALSE;
hi_bool Follow_Switch = HI_FALSE;
hi_bool Obs_Signal = HI_FALSE;
long long int New_Item_Barcode = 0;     // 新商品条码

int g_ligthStatus = -1;
typedef void (*FnMsgCallBack)(hi_gpio_value val);

typedef struct FunctionCallback {
    hi_bool  stop;
    hi_u32 conLost;
    hi_u32 queueID;
    hi_u32 iotTaskID;
    FnMsgCallBack    msgCallBack;
}FunctionCallback;
FunctionCallback g_functinoCallback;

/* Task Sleep time Set */
unsigned int TaskMsleep(unsigned int ms)
{
    if (ms <= 0) {
        return HI_ERR_FAILURE;
    }
    return hi_sleep((hi_u32)ms);
}

static void DeviceConfigInit(hi_gpio_value val)
{
    hi_io_set_func(HI_IO_NAME_GPIO_9, HI_IO_FUNC_GPIO_9_GPIO);
    hi_gpio_set_dir(HI_GPIO_IDX_9, HI_GPIO_DIR_OUT);
    hi_gpio_set_ouput_val(HI_GPIO_IDX_9, val);
}

static int  DeviceMsgCallback(FnMsgCallBack msgCallBack)
{
    g_functinoCallback.msgCallBack = msgCallBack;
    return 0;
}

static void wechatControlDeviceMsg(hi_gpio_value val)
{
    DeviceConfigInit(val);
}

// < this is the callback function, set to the mqtt, and if any messages come, it will be called
// < The payload here is the json string
static void DemoMsgRcvCallBack(int qos, const char *topic, const char *payload)
{
    IOT_LOG_DEBUG("RCVMSG:QOS:%d TOPIC:%s PAYLOAD:%s\r\n", qos, topic, payload);
    /* 云端下发命令后，板端的操作处理 */

    // 如果在收到的消息当中有powerSwitch
    if (strstr(payload, "powerSwitch") != NULL) {
        if (strstr(payload, POWERSWITCH_OFF) != NULL) {//如果是“0”：关闭开关(关灯)
            //wechatControlDeviceMsg(HI_GPIO_VALUE1);
            Detect_Mode = MODE_NONE;
            g_ligthStatus = HI_FALSE;
            Follow_Switch = HI_FALSE;
            IotPublishFollowStatus(); // 发送反馈;
            setLeftMotorSpeed(0);
            setRightMotorSpeed(0);
        } else {//如果是“1”：开启开关(亮灯)
            g_ligthStatus = HI_TRUE;
            Follow_Switch = HI_TRUE;
            IotPublishFollowStatus(); // 发送反馈
        }
    }

    /* 右轮速度 */
    char *ret;
    if ((ret = strstr(payload, "rightSpeed")) != NULL) {
        int speed = getSpeed(ret);
        printf("[RECV] rightSpeed : %d\r\n", speed);
        setRightMotorDuty(speed);
    }

    /*左轮速度*/
    if ((ret = strstr(payload, "leftSpeed")) != NULL) {
        int speed = getSpeed(ret);
        printf("[RECV] leftSpeed : %d\r\n", speed);
        setLeftMotorDuty(speed);
    }
    
    return HI_NULL;
}

/* 反馈给小程序是否成功开启跟随 */
hi_void IotPublishFollowStatus(void)
{
    /* reported attribute */
    WeChatProfile weChatProfile = {
        .subscribeType = "type",
        .status.subState = "state",
        .status.subReport = "reported",
        .status.reportVersion = "version",
        .status.Token = "clientToken",
    };

    /* report power */
    if (Follow_Switch == HI_TRUE) {
        weChatProfile.reportAction.subDeviceActionPowerSwitch = "power";
        weChatProfile.reportAction.PowerSwitchStatus = 1; /* 1: power on */
    } else {
        weChatProfile.reportAction.subDeviceActionPowerSwitch = "power";
        weChatProfile.reportAction.PowerSwitchStatus = 0; /* 0: power off */
    }
    /* profile report */
    IoTProfilePropertyReport(CONFIG_USER_ID, &weChatProfile);
}


/* 上传商品信息 */
hi_void IotPublishNewItem(void)
{
    /* reported attribute */
    WeChatProfile weChatProfile = {
        .subscribeType = "type",
        .status.subState = "state",
        .status.subReport = "reported",
        .status.reportVersion = "version",
        .status.Token = "clientToken",
        /* 上报新增商品 */
        .reportAction.subDeviceActionNewItem = "newItem",
        .reportAction.newItemStatus = New_Item_Barcode, 
    };
    IoTProfilePropertyReport(CONFIG_USER_ID, &weChatProfile);
}


/* 线程入口函数 */
static hi_void *DemoEntry(const char *arg)
{

    gpioMotorControllerInit();//初始化pwm

    cJsonInit();//初始化JSON

    WifiStaReadyWait();//连接wifi

    IoTMain();//创建MQTT线程

    /* 云端下发回调 */
    IoTSetMsgCallback(DemoMsgRcvCallBack);

    long long int barcodeCheck = pow(10,11);

    /* 主动上报 */
    while (1) {
        if (Detect_Mode == MODE_IDENTIFY)
        { 
            car_stop(); // 强制停车
            
            // 检查条码是否识别正确
            if (New_Item_Barcode != 0 && (New_Item_Barcode / barcodeCheck == 69) ){
                IotPublishNewItem(); // 商品上报
                TaskMsleep(5*ONE_SECOND); // 发布完以后停顿，以免重复发布
                New_Item_Barcode = 0; // 重置商品Id
            }
            else{
                TaskMsleep(2*ONE_SECOND); // 对商品进行识别
            }
        }
        PID_control_handler();  // 实施pid控制
        TaskMsleep(0.01*ONE_SECOND); // 线程间隙
    }
    return NULL;
}

// < This is the demo entry, we create a task here,
// and all the works has been done in the demo_entry
#define CN_IOT_TASK_STACKSIZE  0x1000
#define CN_IOT_TASK_PRIOR 28
#define CN_IOT_TASK_NAME "IOTDEMO"

static void AppDemoIot(void)
{
    osThreadAttr_t attr;
    IoTWatchDogDisable();

    attr.name = "IOTDEMO";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = CN_IOT_TASK_STACKSIZE;
    attr.priority = CN_IOT_TASK_PRIOR;

    if (osThreadNew((osThreadFunc_t)DemoEntry, NULL, &attr) == NULL) {
        printf("[mqtt] Falied to create IOTDEMO!\n");
    }
}

SYS_RUN(AppDemoIot);